﻿using System;
using System.IO;
using System.Net.Http.Headers;
using ESoft.Core.Data.Service;
using ESoft.Core.Util.Helpers;
using ESoft.Core.Utils.Extensions;
using ESoft.Core.Web.Common.Filters;
using ESoft.Core.Web.VO;
using ESoft.Portal.Data.Domain;
using ESoft.Portal.Data.Domain.Entity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Configuration;

namespace ESoft.Portal.Controllers
{
    [Route("/api/file")]
    public class FileController : ControllerBase
    {
        private readonly string _basefile = string.Empty;
        private readonly IBaseService _baseService;
        private readonly IMemoryCache _memoryCache;
        private readonly IHostingEnvironment _hostingEnvironment;
        public FileController(IConfiguration configuration, IBaseService baseService, IMemoryCache memoryCache, IHostingEnvironment hostingEnvironment)
        {
            this._baseService = baseService;
            _memoryCache = memoryCache;
            _hostingEnvironment = hostingEnvironment;
            _basefile = hostingEnvironment.WebRootPath + configuration.GetSection("UPLOAD_DIR").Value;
        }

        [HttpPost("upload")]
        [RequestSizeLimit(100 * 1024 * 1024)] //限制http大小
        public object Post(IFormFile file)
        {
            if (file.IsNull())
                return null;
            string fileName = ContentDispositionHeaderValue
                              .Parse(file.ContentDisposition)
                              .FileName
                              .Trim('"');

            string tempFullPath = SaveFile(file, fileName);

            var fileEntity = new CFileEntity
            {
                FileName = fileName,
                FileId = StringHelper.GetId(),
                FilePath = tempFullPath,
                FileExe = Path.GetExtension(fileName),
                CreateDatetime = DateTime.Now,
                MineType = file.ContentType
            };
            _baseService.Add(fileEntity);

            return fileEntity;
        }

        private String SaveFile(IFormFile file, string fileName)
        {
            String tempPath = DateTime.Now.ToString("yyyy-MM-dd");
            string saveDir = Path.Combine(Directory.GetCurrentDirectory(), _basefile, tempPath);
            if (!Directory.Exists(saveDir))
                Directory.CreateDirectory(saveDir);

            var newFileName = Path.GetFileNameWithoutExtension(fileName) + "_" + DateTime.Now.ToString("yyyyMMddHHmmss") + new Random().Next(1000, 90000) + Path.GetExtension(fileName);
            String tempFullPath = Path.Combine(tempPath, $@"{newFileName}");
            var savePath = Path.Combine(_basefile, tempFullPath);
            using (FileStream fs = new FileStream(savePath, FileMode.Create))
            {
                file.CopyTo(fs);
                fs.Flush();
            }
            return tempFullPath;
        }

        [SkipUserAuthorize]
        [HttpGet("download")]
        public IActionResult Get(string fileId)
        {
            if (!_memoryCache.TryGetValue<CFileEntity>("CFileEntity-" + fileId, out var fileEntity))
            {
                fileEntity = this._baseService.Find<CFileEntity>(fileId);
                _memoryCache.Set("CFileEntity-" + fileId, fileEntity);
            }
            if (fileEntity.IsNotNull())
            {
                var addrUrl = Path.Combine(Directory.GetCurrentDirectory(), _basefile, fileEntity.FilePath);
                FileStream fs = new FileStream(addrUrl, FileMode.Open);
                return File(fs, fileEntity.MineType, fileEntity.FileName);
            }
            return NotFound();
        }

        [HttpDelete("delete/{fileId}")]
        public Object Delete(string fileId)
        {
            CFileEntity fileEntity = this._baseService.Find<CFileEntity>(fileId);
            if (fileEntity.IsNotNull())
            {
                var addrUrl = Path.Combine(Directory.GetCurrentDirectory(), _basefile, fileEntity.FilePath);
                if (System.IO.File.Exists(addrUrl))
                {
                    System.IO.File.Delete(addrUrl);
                }
                this._baseService.Delete(fileEntity);
                return ResponseResult.Success();
            }
            return ResponseResult.FailOut("不存在该文件！");
        }
    }
}
